/*
 * Copyright 2018 xwc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.xwc.view;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.TextAlignment;
import ohos.agp.window.dialog.ToastDialog;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.global.resource.ResourceManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.multimodalinput.event.TouchEvent;

import java.util.Optional;

/**
 * Created by xwc on 2018/7/3.
 */
public class ButtonShapeView extends Button implements Component.TouchEventListener {
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x000110, "StateButton");

    private static final int TEXT_SIZE = 40;
    private static final int DURATION_TIME = 2000;
    private static final int TOAST_DIALOG_RADIUS = 3000;
    private static final int DIALOG_PADDING = 20;
    private static final int NUMBER3 = 3;
    private static final int NUMBER8 = 8;
    private static final int NUMBER16 = 16;
    private static final int ALPHA = 95;

    private int radius;
    private int topLeftRadius;
    private int topRightRadius;
    private int bottomRightRadius;
    private int bottomLeftRadius;

    private float[] roundedCorners;

    // button的name
    private String buttonName;

    // 抬起时颜色(with radius/round radius/different radius)
    private RgbColor rgbWhite;

    // 移出button时颜色(with radius/round radius/different radius)
    private RgbColor rgbBlack;

    // 当前点击的button的高度
    private float buttonHeight;

    // 按下时触摸X坐标
    private float downTouchY;

    // button左边界X坐标
    private float leftX;

    // button右边界X坐标
    private float rightX;

    // button上边界Y坐标
    private float topY;

    // button下边界Y坐标
    private float bottomY;

    /**
     * 单参构造
     *
     * @param context
     */
    public ButtonShapeView(Context context) {
        super(context);
    }

    /**
     * 双参构造,默认走这个
     *
     * @param context
     * @param attrSet
     */
    public ButtonShapeView(Context context, AttrSet attrSet) {
        super(context, attrSet);

        // 初始化button
        initButton(attrSet);

        // 设置监听事件
        this.setTouchEventListener(this::onTouchEvent);
    }

    private void initButton(AttrSet attrSet) {
        buttonName = attrSet.getAttr("name").get().getStringValue();

        rgbWhite = new RgbColor(255, 255, 255);
        rgbBlack = new RgbColor(0, 0, 0);
    }

    /**
     * 全参构造
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public ButtonShapeView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
    }

    /**
     * 触摸事件
     *
     * @param cpt
     * @param touchEvent
     * @return boolean
     */
    @Override
    public boolean onTouchEvent(Component cpt, TouchEvent touchEvent) {
        switch (touchEvent.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:

                // 初次按下设置标记: 是否移出button范围
                boolean moveOutOfButtonFlag = false;
                buttonHeight = this.getHeight();
                downTouchY = touchEvent.getPointerScreenPosition(0).getY();

                // 获取button横坐标范围
                leftX = this.getLeft();
                rightX = this.getRight();

                // 计算button纵坐标范围 这里不用this.getTop,this.getBottom,返回值为距父组件的距离,该返回值不是距屏幕顶部的值
                /*
                public int getTop()
                Obtains the top edge position of a component relative to the parent layout.
                这里的计算,假设点击位置都在button高度中心点击,移动偏移1/2高度,就当做移出button范围
                最上边的label和屏幕顶端状态栏还有高度
                 */
                topY = downTouchY - buttonHeight / 2;
                bottomY = downTouchY + buttonHeight / 2;

                if ("keepStroke1".equals(buttonName)) {
                    this.setTextColor(Color.BLACK);
                    ShapeElement keepStrokeEle = (ShapeElement) cpt.getBackgroundElement();
                    keepStrokeEle.setRgbColor(rgbWhite);
                    this.setBackground(keepStrokeEle);
                } else if ("keepStroke2".equals(buttonName)) {
                    this.setTextColor(Color.WHITE);
                    ShapeElement keepStrokeEle = (ShapeElement) cpt.getBackgroundElement();
                    keepStrokeEle.setRgbColor(rgbBlack);
                    this.setBackground(keepStrokeEle);
                } else if ("keepStroke3".equals(buttonName)) {
                    this.setTextColor(Color.BLACK);
                    ShapeElement keepStrokeEle = (ShapeElement) cpt.getBackgroundElement();
                    keepStrokeEle.setRgbColor(rgbWhite);
                    this.setBackground(keepStrokeEle);
                }
                return true;
            case TouchEvent.PRIMARY_POINT_UP:
                if  ("keepStroke1".equals(buttonName)) {
                    this.setTextColor(Color.WHITE);
                    ShapeElement cBackElement = (ShapeElement) cpt.getBackgroundElement();
                    cBackElement.setRgbColor(rgbBlack);
                    this.setBackground(cBackElement);
                    createDialog();
                } else if (("keepStroke2").equals(buttonName)) {
                    this.setTextColor(Color.BLACK);
                    ShapeElement cBackElement = (ShapeElement) cpt.getBackgroundElement();
                    cBackElement.setRgbColor(rgbWhite);
                    this.setBackground(cBackElement);
                } else if ("keepStroke3".equals(buttonName)) {
                    this.setTextColor(Color.WHITE);
                    ShapeElement cBackElement = (ShapeElement) cpt.getBackgroundElement();
                    cBackElement.setRgbColor(rgbBlack);
                    this.setBackground(cBackElement);
                }
                return true;
            default:
        }
        return false;
    }
    private void createDialog() {
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(new RgbColor(Color.BLACK.getValue() >> NUMBER16,
            Color.BLACK.getValue() >> NUMBER8, Color.BLACK.getValue() >> NUMBER3));
        shapeElement.setAlpha(ALPHA);
        DirectionalLayout directionalLayout = new DirectionalLayout(getContext());
        directionalLayout.setBackground(shapeElement);

        directionalLayout.setLayoutConfig(new ComponentContainer
            .LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT,
            ComponentContainer.LayoutConfig.MATCH_CONTENT));
        directionalLayout.setAlignment(LayoutAlignment.CENTER);
        Text dialog = new Text(getContext());
        dialog.setText("     1    ");
        dialog.setTextColor(Color.WHITE);
        dialog.setTextAlignment(TextAlignment.HORIZONTAL_CENTER);
        dialog.setTextSize(TEXT_SIZE, Text.TextSizeType.PX);
        dialog.setPadding(DIALOG_PADDING, DIALOG_PADDING, DIALOG_PADDING, DIALOG_PADDING);
        directionalLayout.addComponent(dialog);
        new ToastDialog(getContext())
            .setSize(ComponentContainer.LayoutConfig.MATCH_CONTENT,
                ComponentContainer.LayoutConfig.MATCH_CONTENT)
            .setComponent(directionalLayout)
            .setDuration(DURATION_TIME)
            .setCornerRadius(TOAST_DIALOG_RADIUS)
            // Toast显示在界面底部
            .setAlignment(LayoutAlignment.BOTTOM)
            .show();
    }

    /**
     * 判断控制点是否在button范围内,X轴计算准确;
     * Y轴计算不准确:这里的计算,假设点击位置都在button高度h的中心点击,
     * 移动偏移1/2高度,就当做移出button范围.
     * bug示例: 当点击位置位于button上边框附近时,向下滑动超过1/2h则会判断为移出button范围,
     * 实际上并未超出button
     * 最上边的label和屏幕顶端状态栏还有高度
     *
     * @param newTouchX
     * @param newTouchY
     * @return boolean
     */
    private boolean isOutOfButton(float newTouchX, float newTouchY) {
        if (newTouchX < leftX) {
            return true;
        } else if (newTouchX > rightX) {
            return true;
        } else if (newTouchY < topY) {
            return true;
        } else if (newTouchY > bottomY) {
            return true;
        }
        return false;
    }

    public int getRadius() {
        return radius;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }

    public int getTopLeftRadius() {
        return topLeftRadius;
    }

    public void setTopLeftRadius(int topLeftRadius) {
        this.topLeftRadius = topLeftRadius;
    }

    public int getTopRightRadius() {
        return topRightRadius;
    }

    public void setTopRightRadius(int topRightRadius) {
        this.topRightRadius = topRightRadius;
    }

    public int getBottomRightRadius() {
        return bottomRightRadius;
    }

    public void setBottomRightRadius(int bottomRightRadius) {
        this.bottomRightRadius = bottomRightRadius;
    }

    public int getBottomLeftRadius() {
        return bottomLeftRadius;
    }

    public void setBottomLeftRadius(int bottomLeftRadius) {
        this.bottomLeftRadius = bottomLeftRadius;
    }

    public float[] getRoundedCorners() {
        float[] corners = roundedCorners;
        return corners;
    }

    public void setRoundedCorners(float[] roundedCorners) {
        this.roundedCorners = roundedCorners.clone();
    }
}
